package control

import (
	"card-platform/config"
	"fmt"
	"github.com/gin-gonic/gin"
	json "github.com/json-iterator/go"
	"io/ioutil"
	"net/http"
	"pkg/cfg"
	"strconv"
	"time"
)

func SetRouter(r *gin.Engine) {
	InitCmd()
	r.POST("upload", Upload)
	// 微信回调
	r.POST("api/wxCallback", WxCallback)
	for k, _ := range _default_cmd_handlers {
		r.POST(k, Api)
	}
}

type Param struct {
}

// HandlerFunc 命令调用
type HandlerFunc func(int64, []byte, Param) (interface{}, int, error)

var (
	_default_cmd_handlers = make(map[string]HandlerFunc)
)

var noAuthMap = make(map[string]bool)

func InitCmd() {

	noAuthMap["/authorizationCode"] = true
	noAuthMap["/wxSign"] = true

	// 用户类
	user := User{}
	_default_cmd_handlers["/authorizationCode"] = user.AuthorizationCode
	_default_cmd_handlers["/wxSign"] = user.WxSign
	_default_cmd_handlers["/userInfo"] = user.UserInfo
	_default_cmd_handlers["/confirmReceipt"] = user.ConfirmReceipt
	_default_cmd_handlers["/userOrderDetail"] = user.UserOrderDetail
	_default_cmd_handlers["/userOrderList"] = user.UserOrderList
	_default_cmd_handlers["/useOrder"] = user.UseOrder
	_default_cmd_handlers["/gainDetail"] = user.GainDetail
	_default_cmd_handlers["/subordinateList"] = user.SubordinateList
	_default_cmd_handlers["/confirmReceipt"] = user.ConfirmReceipt
	_default_cmd_handlers["/userWithdrawList"] = user.UserWithdrawList
	_default_cmd_handlers["/applyUserWithdraw"] = user.ApplyUserWithdraw
	_default_cmd_handlers["/setUserPhone"] = user.SetUserPhone

	// 商户类
	merchant := Merchant{}
	_default_cmd_handlers["/applyMerchant"] = merchant.ApplyMerchant
	_default_cmd_handlers["/merchantType"] = merchant.MerchantType
	_default_cmd_handlers["/getMerchant"] = merchant.GetMerchant
	_default_cmd_handlers["/merchantList"] = merchant.MerchantList
	_default_cmd_handlers["/auditMerchant"] = merchant.AuditMerchant
	_default_cmd_handlers["/nearbyMerchant"] = merchant.NearbyMerchant
	_default_cmd_handlers["/getQrDetail"] = merchant.GetQrDetail
	_default_cmd_handlers["/verifyQr"] = merchant.VerifyQr
	_default_cmd_handlers["/merchantOrderList"] = merchant.MerchantOrderList
	_default_cmd_handlers["/merchantOrderDetail"] = merchant.MerchantOrderDetail
	_default_cmd_handlers["/deliverOrder"] = merchant.DeliverOrder
	_default_cmd_handlers["/editOrderPrice"] = merchant.EditOrderPrice

	// 商品类
	pro := Pro{}
	_default_cmd_handlers["/createPro"] = pro.CreatePro
	_default_cmd_handlers["/proList"] = pro.ProList
	_default_cmd_handlers["/updatePro"] = pro.UpdatePro
	_default_cmd_handlers["/proDetails"] = pro.ProDetails
	_default_cmd_handlers["/proCheck"] = pro.ProCheck
	_default_cmd_handlers["/pros"] = pro.Pros
	_default_cmd_handlers["/delPro"] = pro.DelPro

	//收货地址
	logistics := Logistics{}
	_default_cmd_handlers["/createLogistics"] = logistics.CreateLogistics
	_default_cmd_handlers["/delLogistics"] = logistics.DelLogistics
	_default_cmd_handlers["/logisticsList"] = logistics.LogisticsList
	_default_cmd_handlers["/logisticsDetails"] = logistics.LogisticsDetails

	// 订单
	order := Order{}
	_default_cmd_handlers["/buyCard"] = order.BuyCard
	_default_cmd_handlers["/buyPro"] = order.BuyPro
	_default_cmd_handlers["/prepositionBuyPro"] = order.PrepositionBuyPro
	_default_cmd_handlers["/getOrderPay"] = order.GetOrderPay

	//发卡
	card := Card{}
	_default_cmd_handlers["/cardFeed"] = card.CardFeed
	_default_cmd_handlers["/cardCollect"] = card.CardCollect
	_default_cmd_handlers["/cardList"] = card.CardList

}

func Upload(c *gin.Context) {
	path, err := uploadImg(c, "img")
	if err != nil {
		cfg.LogErr("网络错误:", err.Error())
		_, err := c.Writer.Write(encode(config.ERR_READ_HTTP_DATA, "", nil))
		if err != nil {
			cfg.LogErr("err:" + err.Error())
		}
		return
	}
	out := make(map[string]string)
	out["path"] = path
	_, err = c.Writer.Write(encode(0, "", out))
	if err != nil {
		//cfg.LogInfof("err:", err.Error())
	}
	return
}

func Api(c *gin.Context) {
	path := c.Request.URL.Path
	cfg.LogInfo("path:" + path)
	startTime := time.Now()
	data, err := ioutil.ReadAll(c.Request.Body)
	if err != nil {
		cfg.LogErr("网络错误:", err.Error())
		_, err := c.Writer.Write(encode(config.ERR_READ_HTTP_DATA, "", nil))
		if err != nil {
			cfg.LogErr("err:" + err.Error())
		}
		return
	}

	var userId int64
	if _, ok := noAuthMap[path]; !ok {
		userIdStr := c.GetHeader("userId")
		token := c.GetHeader("token")
		userId, err = strconv.ParseInt(userIdStr, 10, 64)
		if err != nil {
			_, err := c.Writer.Write(encode(config.ERR_NOT_LOGIN, "用户未登录,请登录", nil))
			if err != nil {
				cfg.LogErr("err:" + err.Error())
			}
			return
		}
		cfg.LogInfo("userIdStr:", userIdStr, ",userId:", userId)
		userId, err = CheckUserAuth(token, userId)
		if err != nil {
			cfg.LogErr("err:", err)
			_, err := c.Writer.Write(encode(config.ERR_NOT_LOGIN, err.Error(), nil))
			if err != nil {
				cfg.LogErr("err:" + err.Error())
			}
			return
		}

		if userId <= 0 {
			_, err := c.Writer.Write(encode(config.ERR_NOT_LOGIN, "用户未登录,请登录", nil))
			if err != nil {
				cfg.LogErr("err:" + err.Error())
			}
			return
		}
	}

	param := Param{}
	if f, ok := _default_cmd_handlers[path]; ok {
		res, code, err := f(userId, data, param)
		if err != nil {
			_, err := c.Writer.Write(encode(code, err.Error(), nil))
			if err != nil {
				cfg.LogErr("err:", err.Error())
			}
			cfg.LogErrf("异常接口,userId:%d,path:%s,耗时:%s,in:%s", userId, path, time.Now().Sub(startTime).String(), string(data))
			return
		}
		resp := encode(0, "", res)
		_, err = c.Writer.Write(resp)
		if err != nil {
			//cfg.LogInfof("err:", err.Error())
		}
		cfg.LogInfof("path:%s,userId:%d,remoteAddr:%s,耗时:%s,in:%s,out:%v", path, userId, c.Request.RemoteAddr, time.Now().Sub(startTime).String(), string(data), string(resp))
		return
	} else {
		_, err = c.Writer.Write(encode(config.FOUND_NOT_ERROR, fmt.Sprintf("接口%s不存在", path), nil))
		if err != nil {
			cfg.LogErr("err:", err.Error())
		}
		return
	}
}

func encode(code int, msg string, obj interface{}) []byte {
	if obj == nil {
		obj = NullObj{}
	}
	out := ResultObj{code, msg, obj}
	b, err := json.Marshal(out)
	if err != nil {
		cfg.LogErr("Encode json失败:", err.Error())
	}
	return b
}

type NullObj struct {
}

type ResultObj struct {
	Code int         `json:"code"`
	Msg  string      `json:"msg"`
	Data interface{} `json:"data"`
}

func Cors() gin.HandlerFunc {
	return func(context *gin.Context) {
		method := context.Request.Method
		context.Writer.Header().Set("Access-Control-Allow-Origin", "*")
		context.Header("Access-Control-Allow-Origin", "*") // 设置允许访问所有域
		context.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE")
		context.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session,X_Requested_With,Accept, Origin, Host, Connection, Accept-Encoding, Accept-Language,DNT, X-CustomHeader, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Pragma,token,openid,opentoken,userId")
		context.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers,Cache-Control,Content-Language,Content-Type,Expires,Last-Modified,Pragma,FooBar")
		context.Header("Access-Control-Max-Age", "172800")
		context.Header("Access-Control-Allow-Credentials", "false")
		context.Set("content-type", "application/json")

		if method == "OPTIONS" {
			context.JSON(http.StatusOK, nil)
		}
		//处理请求
		context.Next()
	}
}
